﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Data;
using Skynet.CommonLibrary.Extension.Log;
using System.Diagnostics;
using IDataCenterContract;
using System.Text;

namespace DataCenterService
{
    public class DownLoadFile : IDownLoadFile
    {
       
        #region IDownLoadFile 成员

        public bool IsDown(string versionNumber, string programName)
        {
            LogService.GlobalInfoMessage("调用IsDown，VersionNumber=" + versionNumber + ",ProgramName=" + programName);
            if (string.IsNullOrEmpty(versionNumber) || string.IsNullOrEmpty(programName))
                return true;
            try
            {
                decimal currentVersion = Convert.ToDecimal( string.Join("", versionNumber.Split(new char[]{'.'}, StringSplitOptions.RemoveEmptyEntries)));
                decimal DownVersion = Convert.ToDecimal(string.Join("", FileHelper.GetVersion(programName).Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries)));
                if (currentVersion < DownVersion)
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        public byte[] DownLoadFirst(string fileName)
        {
            return FileHelper.GetFile(fileName);
        }

        public byte[] DownLoadShare(string fileName, long length)
        {
            return FileHelper.GetShareFile(fileName, length);
        }

        public DataTable DownLoadFileNames()
        {
            LogService.GlobalInfoMessage("调用DownLoadFileNames");
            return FileHelper.GetDictionaryFile();
        }
        #endregion
    }

    public static class FileHelper
    {
        private static readonly string DownPath = AppDomain.CurrentDomain.BaseDirectory + "\\DownLoad";

        static FileHelper()
        {
           
        }
        /// <summary>
        /// 获取文件MD5校验值
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <returns></returns>
        public static string GetMD5HashFromFile(string fileName)
        {
            if (File.Exists(fileName))
            {
                byte[] retVal = null;
                using (FileStream file = File.OpenRead(fileName))
                {
                    System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                    retVal = md5.ComputeHash(file);
                }
                if (retVal != null)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < retVal.Length; i++)
                    {
                        sb.Append(retVal[i].ToString("x2"));
                    }
                    return sb.ToString().Trim().ToUpper();
                }
            }
            return string.Empty;
        }
        /// <summary>
        /// 获取该目录下主程序的版本号
        /// </summary>
        /// <returns></returns>
        public static string GetVersion(string programName)
        {
            if (!Directory.Exists(DownPath))
            {
                return string.Empty;
            }

            if (Directory.GetFiles(DownPath).FirstOrDefault(o => System.IO.Path.GetFileName(o) == programName) != null)
            {
                FileVersionInfo fInfo = FileVersionInfo.GetVersionInfo(DownPath + "\\" + programName);
                return fInfo.FileVersion;
            }
            //不存在此版本的程序
            return string.Empty;
        }

        /// <summary>
        /// 获取 目录下所有的 文件名及修改时间
        /// </summary>
        /// <returns></returns>
        public static DataTable GetDictionaryFile()
        {
            DataTable dt = new DataTable("table");
            dt.Columns.Add("File", typeof(string));
            dt.Columns.Add("Time", typeof(DateTime));
            dt.Columns.Add("Size", typeof(long));
            dt.Columns.Add("ExistThenUpdate", typeof (Boolean));
            dt.Columns.Add("FileVersion", typeof(string));
            dt.Columns.Add("MD5", typeof(string));


            //获取 某些只需要判断是否存在的DLL 
            List<string> list = new List<string>();
            if(File.Exists(DownPath + "\\DoesNotExistThenUpdate.txt"))
            {
                list.AddRange(File.ReadAllLines(DownPath + "\\DoesNotExistThenUpdate.txt"));
            }
            GetFileInfo(DownPath, dt,list);
            return dt;
        }
        private static void GetFileInfo(string dir, DataTable dt,List<string> list)
        {
            foreach (string dirinfo in Directory.GetDirectories(dir))
            {
                GetFileInfo(dirinfo, dt, list);
            }

            foreach (string file in Directory.GetFiles(dir))
            {
                FileInfo info = new FileInfo(file);
                FileVersionInfo fInfo = FileVersionInfo.GetVersionInfo(file);

                dt.Rows.Add(file.Replace(DownPath + "\\", ""),
                    info.LastWriteTime,
                    info.Length,
                    true,
                    fInfo.FileVersion,
                    GetMD5HashFromFile(info.FullName));

            }
        }

        public static byte[] GetFile(string filepath)
        {
            return File.ReadAllBytes(DownPath + "\\" + filepath);
        }

        public static byte[] GetShareFile(string filepath, long length)
        {
            using (FileStream stream = new FileStream(DownPath + "\\" + filepath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                if (stream.Length == length)
                    return null;
                stream.Seek(length, SeekOrigin.Begin);
                
                long longg = 5 * 1024;
                if (longg > stream.Length - length)
                {
                    longg = stream.Length - length;
                }
                byte[] data = new byte[longg];
                stream.Read(data, 0, data.Length);
                return data;
            }
        }
    }
}
